package ru.edu.niimm.mapping.linguistic;

import LemmatizerWrapper.Wordform;
import LemmatizerWrapper.Paradigm;

import java.util.List;
import java.util.ArrayList;
import java.util.TreeMap;

import gate.util.Out;
import cern.colt.matrix.impl.DenseDoubleMatrix2D;

/**
 * Created by IntelliJ IDEA.
 * User: Pooh
 * Date: 19.07.2007
 * Time: 18:37:25
 * To change this template use File | Settings | File Templates.
 */
public class Template {
    int wordCount;
    List<GramUnit> units;

    public Template()
    {
    }

    public Template(int wordCount, List<GramUnit> units) {
        this.wordCount = wordCount;
        this.units = units;
    }

    public GramUnit getMainUnit()
    {
        for(GramUnit unit : units.toArray(new GramUnit[0]))
        {
            if(unit.isMainUnit)
            {
                return unit;
            }
        }
        return null;
    }

    private String concatGramUnitsPOS()
    {
        String res = "";
        for(GramUnit unit : this.units)
        {
            res += unit.getPos() + " ";
        }
        return res;
    }

    private boolean checkTemplateOn1Word(List<Wordform> candidate)
    {
            Wordform wf = candidate.get(0);
            if(wf.paradigms != null)
            {
                for (Paradigm para : wf.paradigms)
                {
                    if(para.pos.equalsIgnoreCase(this.getMainUnit().getPos()))
                    {
                        if(wf.gram_codes != null)
                        {
                            for (String[] gram_code : wf.gram_codes)
                            {
                                for (String aGram_code : gram_code)
                                {
                                    if(aGram_code.contains(this.getMainUnit().gramCodeValue)
                                            && !aGram_code.contains("0,"))
                                    {
                                        Out.println("\n1 word: " + wf.paradigms[0].lemma);
                                        Out.println("@"+wf.paradigms[0].pos);

                                        return true;
                                    }
                                }
                            }
                        }
                    }

                }
            }

        return false;
    }


    private boolean checkTemplateOn2Words(List<Wordform> candidate)
    {
        for(int k = 0; k < candidate.size(); k++)
            {
                if(candidate.get(k).paradigms != null)
                {
//                    for (Paradigm para : candidate.get(k).paradigms)
//                    {
                    Paradigm para = candidate.get(k).paradigms[0];
                        for(GramUnit unit1 : units.toArray(new GramUnit[0]))
                        {
                            if(para.pos.equalsIgnoreCase(unit1.getPos()))
                            {   // POS matches

                                if(candidate.get(1 - k).paradigms != null)
                                {
//                                    for (Paradigm para2 : candidate.get(1 - k).paradigms)
//                                    {
                                    Paradigm para2 = candidate.get(1 - k).paradigms[0];
                                        for(GramUnit unit2 : units.toArray(new GramUnit[0]))
                                        {
                                            if(unit2 != unit1 && para2.pos.equalsIgnoreCase(unit2.getPos()))
                                            {
                                                //POS matches !!!
                                                Wordform wf1 = candidate.get(k);
                                                Wordform wf2 = candidate.get(1 - k);
                                                if(wf1.gram_codes != null)
                                                {
                                                    for (String[] gram_code : wf1.gram_codes)
                                                    {
                                                        for (String aGram_code : gram_code)
                                                        {
                                                            if(wf2.gram_codes != null && aGram_code.contains(unit1.gramCodeValue)
                                                                    && !aGram_code.contains("0,"))
                                                            {
                                                                for (String[] gram_code2 : wf2.gram_codes)
                                                                {
                                                                    for (String aGram_code2 : gram_code2)
                                                                    {
                                                                        if(aGram_code2.contains(unit2.gramCodeValue) &&
                                                                                !aGram_code2.contains("0,"))
                                                                        {
                                                                            Out.println("\n2 word: " + wf1.paradigms[0].lemma + " " + wf2.paradigms[0].lemma);
                                                                            Out.println("@" + wf1.paradigms[0].pos + " " + wf2.paradigms[0].pos);
//                                                                            Out.println(wf1.word + " " + "@" + wf1.paradigms[0].pos + aGram_code + "\n" + wf2.word   + " @"+ wf2.paradigms[0].pos + " " + aGram_code2);
                                                                            return true;
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
//                                }
//
//                            }
                        }
                    }
                }
                // у к-го нет ни одной парадигмы
                else
                {

                }
            }
            return false;
    }

    private boolean checkTemplateOn3Words(List<Wordform> candidate)
    {
        if(candidate.get(0).paradigms != null)
            {
                for (Paradigm para0 : candidate.get(0).paradigms)
                {
                   GramUnit unit0 = this.getMainUnit();

                        if(para0.pos.equalsIgnoreCase(unit0.getPos()))
                        {
                            for(int k = 2; k >= 1; k--)
                            {
                                if(candidate.get(k).paradigms != null)
                                {
                                    for (Paradigm para : candidate.get(k).paradigms)
                                    {
                                        for(GramUnit unit : units.toArray(new GramUnit[0]))
                                        {
                                            if(para.pos.equalsIgnoreCase(unit.getPos()))
                                            {
                                                if(candidate.get(3 - k).paradigms != null)
                                                {
                                                    for (Paradigm para2 : candidate.get(3 - k).paradigms)
                                                    {
                                                        for(GramUnit unit2 : units.toArray(new GramUnit[0]))
                                                        {
                                                            if(unit2 != unit && para2.pos.equalsIgnoreCase(unit2.getPos()))
                                                            {
                                                                //POS matches !!!
                                                                Wordform wf1 = candidate.get(k);
                                                                Wordform wf2 = candidate.get(3 - k);
                                                                if(wf1.gram_codes != null)
                                                                {
                                                                    for (String[] gram_code : wf1.gram_codes)
                                                                    {
                                                                        for (String aGram_code : gram_code)
                                                                        {
                                                                            if(wf2.gram_codes != null && aGram_code.contains(unit.gramCodeValue)
                                                                                    && !aGram_code.contains("0,"))
                                                                            {
                                                                                for (String[] gram_code2 : wf2.gram_codes)
                                                                                {
                                                                                    for (String aGram_code2 : gram_code2)
                                                                                    {
                                                                                        if(aGram_code2.contains(unit2.gramCodeValue) &&
                                                                                                !aGram_code2.contains("0,"))
                                                                                        {
                                                                                            Out.println("\n3 word: " +candidate.get(0).paradigms[0].lemma + " " + candidate.get(1).paradigms[0].lemma + " " + candidate.get(2).paradigms[0].lemma);
                                                                                            Out.println("@"+candidate.get(0).paradigms[0].pos + " " + candidate.get(1).paradigms[0].pos + " " + candidate.get(2).paradigms[0].pos);
                                                                                            return true;
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }

                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return false;
    }

    private boolean checkTemplateOnMoreThan3Words(List<Wordform> candidates)
    {
        DenseDoubleMatrix2D templateMatrix = new DenseDoubleMatrix2D(5, this.getWordCount());
        int i = 0;
        for(GramUnit unit : this.units)
        {

           if(unit.getPos().equalsIgnoreCase("С"))
           {
                templateMatrix.setQuick(0, i, 100);
           }
            if(unit.getPos().equalsIgnoreCase("П"))
           {
                templateMatrix.setQuick(1, i, 100);
           }
            if(unit.getPos().equalsIgnoreCase("Г"))
           {
                templateMatrix.setQuick(2, i, 100);
           }
            if(unit.getPos().equalsIgnoreCase("ПРИЧАСТИЕ"))
           {
                templateMatrix.setQuick(3, i, 100);
           }
            if(unit.getPos().equalsIgnoreCase("ИНФИНИТИВ"))
           {
                templateMatrix.setQuick(4, i, 100);
           }
           i++;
        }


        DenseDoubleMatrix2D candidateMatrix = new DenseDoubleMatrix2D(5, candidates.size());
        i = 0;
        for(Wordform candidate : candidates)
        {
            if(candidate.paradigms != null)
            {
                if(candidate.paradigms.length >= 1)
                {
                    for(Paradigm para : candidate.paradigms)
                    {
                        if(para.pos.equalsIgnoreCase("С"))
                        {
                            candidateMatrix.setQuick(0, i, 100);
                        }
                        if(para.pos.equalsIgnoreCase("П"))
                        {
                            candidateMatrix.setQuick(1, i, 100);
                        }
                        if(para.pos.equalsIgnoreCase("Г"))
                        {
                            candidateMatrix.setQuick(2, i, 100);
                        }
                        if(para.pos.equalsIgnoreCase("ПРИЧАСТИЕ"))
                        {
                            candidateMatrix.setQuick(3, i, 100);
                        }
                        if(para.pos.equalsIgnoreCase("ИНФИНИТИВ"))
                        {
                            candidateMatrix.setQuick(4, i, 100);
                        }
                    }
                }
            }
            i++;
        }

        DenseDoubleMatrix2D multi = myMmult(templateMatrix, candidateMatrix);

        return multi.zSum() >= 10000 * candidates.size();

        /*ArrayList<ArrayList<String>> candidatePOS = new ArrayList<ArrayList<String>>(candidates.size());

        String candidatewords = "";
        for(Wordform candidate : candidates)
        {
            if(candidate.paradigms != null)
            {
                if(candidate.paradigms.length >= 1)
                {
                    ArrayList<String> POSvariants = new ArrayList<String>(candidate.paradigms.length);
                    for(Paradigm para : candidate.paradigms)
                    {
                        POSvariants.add(para.pos);
                    }
                    candidatePOS.add(POSvariants);
                }
//                else
//                {
//                candidatePOS += candidate.paradigms[0].pos + " ";
//                candidatewords += candidate.paradigms[0].lemma + " ";
//                }
            }
        }
        for(ArrayList<String> i : candidatePOS)
        {
            for(int k = 0; k < this.getWordCount(); k++)
            {

            }
            for(ArrayList<String> j : candidatePOS)
            {
                for(String s : i)
                {
                    stringPOS += s;
                }
            }
        }
        if(stringPOS.equalsIgnoreCase(this.concatGramUnitsPOS()))
        {
            Out.println(candidates.size() + " words " + candidatewords);
            Out.println("@" + candidatePOS + " = " + this.concatGramUnitsPOS());
        }


        return candidatePOS.equalsIgnoreCase(this.concatGramUnitsPOS());*/

    }
    private DenseDoubleMatrix2D myMmult(DenseDoubleMatrix2D templateMatrix, DenseDoubleMatrix2D candidateMatrix)
    {
        for(int i = 0; i < templateMatrix.rows(); i++)
        {
            for(int j = 0; j < templateMatrix.columns(); j++)
            {
                templateMatrix.setQuick(i, j, templateMatrix.getQuick(i, j)*candidateMatrix.getQuick(i, j));
            }
        }
        return templateMatrix;
    }
    public boolean checkTemplateOn(List<Wordform> candidate)
    {
        if(wordCount != candidate.size())
        {
            return false;
        }
//
//        if(wordCount == 1)
//        {
//            return  checkTemplateOn1Word(candidate);
//        }
//
//        if(wordCount == 2 )
//        {
//           return  checkTemplateOn2Words(candidate);
//        }

//        if(wordCount == 3 )
//        {
//            return  checkTemplateOn3Words(candidate);
//        }

        if(wordCount >= 1 )
        {
            return  checkTemplateOnMoreThan3Words(candidate);
        }

        return false;
    }

    public boolean checkDateTemplateOn(String date)
    {
        return date.matches("[1-2][0-9][0-9][0-9]");
    }

    public boolean checkCenturyTemplateOn(String date)
    {
        return  date.matches("[X,I,V]")
               || date.matches("[X,I,V][X,I,V]")
               || date.matches("[X,I,V][X,I,V][X,I,V]")
               || date.matches("[X,I,V][X,I,V][X,I,V][X,I,V]")
               || date.matches("[X,I,V][X,I,V][X,I,V][X,I,V][X,I,V]")
               || date.matches("[X,I,V][в,В]")
               || date.matches("[X,I,V][X,I,V][в,В]")
               || date.matches("[X,I,V][X,I,V][X,I,V][в,В]")
               || date.matches("[X,I,V][X,I,V][X,I,V][X,I,V][в,В]")
               || date.matches("[X,I,V][X,I,V][X,I,V][X,I,V][X,I,V][в,В]");
    }

    private boolean isCandidateCoherence(List<Wordform> candidate)
    {
        Wordform wf1 = candidate.get(0);
        Wordform wf2 = candidate.get(1);
        if(wf1.gram_codes != null)
        {
            for (String[] gram_code : wf1.gram_codes)
            {
                for (String aGram_code : gram_code)
                {
                    if(wf2.gram_codes != null)
                    {
                        for (String[] gram_code2 : wf2.gram_codes)
                        {
                            for (String aGram_code2 : gram_code2)
                            {
                                if(isGramCodesCoherence(aGram_code, aGram_code2))
                                {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }
    private boolean isGramCodesCoherence(String code1, String code2)
    {
        String[] codes1 = code1.split(",");
        String[] codes2 = code2.split(",");

        return false;
    }
    public int getWordCount()
    {
        return this.wordCount;
    }
}
